# -*- encoding:utf-8 -*-
from exts import db
from datetime import datetime
# 导入加密密码生成器，检查密码生成器
from werkzeug.security import generate_password_hash,check_password_hash

# 进行权限的定义，继承于object，object是用来干嘛的
class BACKPermission(object):
    # 1.所有权限
    ALL_PERMISSION = 0b11111111
    # 2.访问者
    VISITOR        = 0b00000001
    # 3.管理帖子
    POSTER         = 0b00000010
    # 4.管理评论
    COMMENTER      = 0b00000100
    #5.管理板块的权限
    BOARDER        = 0b00001000
    # 6.管理前台用户的权限
    FRONTUSER      = 0b00010000
    #7.管理后台用户的权限
    BACKUSER       = 0b00100000

# 角色与用户为多对多关系，需要建立中间表
#在BACK_ROLE   BACK_USER前建立中间表
back_user_role = db.Table(
    'back_user_role',
    db.Column('back_user_id',db.Integer,db.ForeignKey("back_user.id"),primary_key=True),
    db.Column('back_role_id',db.Integer,db.ForeignKey("back_role.id"),primary_key=True)
)


#进行角色的定义,定义不同角色拥有的一个或者多个权限
class BACKRole(db.Model):
    __tablename__= 'back_role'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), nullable=False)
    desc =db.Column(db.String(200),nullable=True)
    create_time = db.Column(db.DateTime,default=datetime.now)
    permissions = db.Column(db.Integer,default=BACKPermission.VISITOR)

    #中间表建立后，进行相关表的绑定,
    #backref的使用可以反向查找，如果不用
    #backref，则需要在两个模型中各添加一个访问对方的属性
    #users作为通过BCAKROLE访问user的信息的属性，与此同时roles作为BACKUser访
    # 问BACKRole的属性，如何取名，没有必要要求
    users = db.relationship('BACKUser',secondary=back_user_role,backref='roles')


class BACKUser(db.Model):
    __tablename__ = 'back_user'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    username = db.Column(db.String(50),nullable=False)
    # 对密码加密，对外叫做password，对内叫做_password
    _password = db.Column(db.String(200),nullable=False)
    email = db.Column(db.String(50),nullable=False,unique=True)
    #default 默认值，datetime.now服务器第一运行时间，datetime.now()每次运行时间
    join_time = db.Column(db.DateTime,default=datetime.now)

    # 用法 原理 目的  其他试用场所，与manage文件中password进行连接，以便
    def __init__(self,username,password,email):
        # python中的self就相当于C++中的this指针，也就是指向对象本身的指针，
        # self.name = name 就是当前对象的成员变量name赋值为name。
        # manage.py中的username password email相关信息传入这里进行加工，为后续hash处理存储进入数据库做准备
        self.username = username
        self.password = password
        self.email = email

    # @property与@password.setter用法
    # 用法  目的  其他试用场所
    @property
    def password(self):
        return self._password

    # 用法  目的  其他试用场所
    @password.setter
    # 生成加密密码
    def password(self,raw_password):
        # 将原始密码加密生产_password
        self._password = generate_password_hash(raw_password)


    # 检查密码
    def check_password(self,raw_password):
        result = check_password_hash(self._password,raw_password)
        return result

    #获取用户所有权限的功能完成
    #property装饰器可以将函数转化为属性，以便访问
    @property
    def permissions(self):
        # 判断用户角色
        #如果没有用户
        if not self.roles:
            #二进制决定此处为0
            return 0
        #有用户则查找角色并赋予角色
        all_permissions=0
        # 遍历然后迭代角色累加
        # print(self.roles)
        for role in self.roles:
            # print(role)
            permissions=role.permissions
            # print(permissions)
            all_permissions |=permissions
            # print(all_permissions)
        return all_permissions

    # 传入权限，判断是否拥有权限
    def has_permissions(self,permission):
        # all_permissions=self.permissions
        # result=all_permissions&permission==permission
        # return result
        #以上三句话简化为一句话
        # 此处的permissions指向
        return self.permissions&permission==permission

    # 判断是否为开发者
    @property
    def is_developer(self):
        return self.has_permissions(BACKPermission.ALL_PERMISSION)

